package util;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;
import java.util.List;

/**
 * zkService工具。zk是单链接的，本来支持事物。
 *
 * 每次手动设置watch为true，以后才能得到watch事件。 例如：exists(path,watch)
 * PS:每次倒要设置watch为true，下次才能捕获到watch事件。
 */
@SuppressWarnings("all")
public class ZkService {
    public static final int NO_VERSION = -1 ;

    private static ZkConnectPool pool = new ZkConnectPool();
    static {
        try {
            pool.initConnectPool();
        }catch (Exception e){
            e.printStackTrace();
        }
    }


    /**
     * 插入临时节点（需要手动删除，不支持递归路径）
     * @param path  路径
     * @param data  节点内容
     * @return
     */
    public boolean insertEphemeralNode(String path,String data){
        ZkConnect connect=null;
        try {
            if ( data == null  || path == null || path.trim().equals("") || !ZkUtil.CheckPath(path)) return false;
            connect= pool.getZkConnect();
           if(connect.exists(path,true) != null) return false;
            connect.create(path,data.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
            return true;
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (connect !=null) connect.releaseZkConnect();
        }
        return false;
    }


    /**
     * 插入永久节点，不支持递归路径
     * @param path
     * @param data
     * @return
     */
    public boolean insertPersistemtNode(String path,String data){
        ZkConnect connect=null;
        try {
            if ( data == null  || path == null || path.trim().equals("") || !ZkUtil.CheckPath(path)) return false;
            connect= pool.getZkConnect();
            if(connect.exists(path,true) != null) return false;
            connect.create(path,data.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            return true;
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (connect !=null) connect.releaseZkConnect();
        }
        return false;
    }


    /**
     * 删除节点，不支持递归路径
     * @param path
     * @param version
     * @return
     */
    public boolean deleteNode(String path,Integer version){
        ZkConnect connect=null;
        try {
            if (  path == null || path.trim().equals("") || !ZkUtil.CheckPath(path)) return false;
            connect= pool.getZkConnect();
            if(connect.exists(path,true) == null) return false;
            if (version !=null)
            connect.delete(path,version);
            else if(version ==null)
            connect.delete(path,NO_VERSION);
            return true;
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (connect !=null) connect.releaseZkConnect();
        }
        return false;
    }


    /**
     * insertOrUpdate 实现永久节点的修改，不支持递归路径
     * @param path
     * @param data
     * @param version 无：不检查版本   有：乐观锁检查版本信息
     * @return
     */
    public boolean mergerPersistemtNode(String path,String data,Integer version){
        ZkConnect connect=null;
        try {
            if (data != null || path == null || path.trim().equals("") || !ZkUtil.CheckPath(path)) return false;
            connect= pool.getZkConnect();
            if(connect.exists(path,true) == null)
                connect.create(path,data.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            else
                connect.setData(path,data.getBytes(), version == null ? NO_VERSION : version );
            return true;
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (connect !=null) connect.releaseZkConnect();
        }
        return false;
    }



    /**
     * insertOrUpdate 实现临时节点的修改，不支持递归路径
     * @param path
     * @param data
     * @param version 无：不检查版本   有：乐观锁检查版本信息
     * @return
     */
    public boolean mergerEphemeralNode(String path,String data,Integer version){
        ZkConnect connect=null;
        try {
            if (data != null || path == null || path.trim().equals("") || !ZkUtil.CheckPath(path)) return false;
            connect= pool.getZkConnect();
            if(connect.exists(path,true) == null)
                connect.create(path,data.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
            else
                connect.setData(path,data.getBytes(), version == null ? NO_VERSION : version );
            return true;
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (connect !=null) connect.releaseZkConnect();
        }
        return false;
    }


    /**
     * 得到节点的data数据
     * @param path
     * @return
     */
    public String getNodeData(String path){
        ZkConnect connect=null;
        try {
            if ( path == null || path.trim().equals("") || !ZkUtil.CheckPath(path)) return null;
            connect= pool.getZkConnect();
            byte[] data=connect.getData(path,true,null);
            if (data ==null) return null;
            return new String(data);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (connect !=null) connect.releaseZkConnect();
        }
        return null;
    }



    /**
     * 是否含有该节点
     * @param path
     * @return
     */
    public boolean hasNode(String path)throws Exception{
        ZkConnect connect=null;
        try {
            if ( path == null || path.trim().equals("") || !ZkUtil.CheckPath(path)) throw new NullPointerException("path is illegal");
            connect= pool.getZkConnect();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (connect !=null) connect.releaseZkConnect();
        }

        return connect.exists(path,true) == null ? false : true ;
    }


    /**
     *得到子节点
     * @param path
     * @return
     * @throws Exception
     */
    public List<String> getChildrenNode(String path)throws Exception{
        ZkConnect connect1=null;
        try {
            if ( path == null || path.trim().equals("") || !ZkUtil.CheckPath(path)) return null;
            connect1= pool.getZkConnect();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (connect1 !=null) connect1.releaseZkConnect();
        }
        return connect1.getChildren(path,true);
    }

    


    public static void main(String[] arys)throws Exception{
        ZkService service=new ZkService();
        System.out.println(service.insertEphemeralNode("/li","lisi"));
        System.out.println(service.insertEphemeralNode("/wang","wangwu"));
        System.out.println(service.getNodeData("/wang"));
        System.out.println(service.hasNode("/wang2"));
        System.out.println(service.getChildrenNode("/"));



       /* System.out.println(CheckPath("ssa"));
        System.out.println(CheckPath("/saa/"));*/

    }






}
